import com.sun.source.tree.*;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;


import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;

import java.io.IOException;
import java.util.ArrayList;

import static java.nio.charset.Charset.*;

/**
 * Created by 矩阵 on 2017/12/17.
 */
public class ScannerDemo {
    private JavacFileManager fileManager;
    private JavacTool javacTool;

    public ScannerDemo() {
        Context context = new Context();
        fileManager = new JavacFileManager(context,true, defaultCharset());
        javacTool = JavacTool.create();
    }

    public void parseJavaFile(String path){
        ArrayList<JavaFileObject> fileObject = (ArrayList<JavaFileObject>) fileManager.getJavaFileObjects(path);
        JavaCompiler.CompilationTask compilationTask = javacTool.getTask(null,fileManager,null,null,null,fileObject);
        JavacTask javacTask = (JavacTask) compilationTask;
        try {
            Iterable<CompilationUnitTree> result = (Iterable<CompilationUnitTree>) javacTask.parse();
            for (CompilationUnitTree tree:result){
                tree.accept(new SourceVisitor(),null);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        new ScannerDemo().parseJavaFile("F:\\java\\MyService.java");
    }

    static class SourceVisitor extends TreeScanner<Void,Void>{
        private String currentPackageName = null;

        @Override
        public Void visitCompilationUnit(CompilationUnitTree node, Void aVoid) {
            return super.visitCompilationUnit(node, aVoid);
        }

//        @Override
//        public Void visitVariable(VariableTree node, Void aVoid) {
//            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
//                    node.getName(), node.getType(), node.getKind(), currentPackageName);
//            return null;
//        }

//        @Override
//        public Void visitMethod(MethodTree node, Void aVoid){
//            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
//                    node.getName(), node.getModifiers(), node.getKind(), node.getBody());
//            return null;
//        }
//
//        @Override
//        public Void visitNewClass(NewClassTree node, Void aVoid) {
//            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
//                    node.getIdentifier(), node.getClassBody(), node.getKind(), node);
//            return null;
//            r = scanAndReduce(node.getIdentifier(), p, r);
//            r = scanAndReduce(node.getTypeArguments(), p, r);
//            r = scanAndReduce(node.getArguments(), p, r);
//            r = scanAndReduce(node.getClassBody(), p, r);
//            return r;
//        }

//        @Override
//        public Void visitMethodInvocation(MethodInvocationTree node, Void aVoid) {
//            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
//                    node.getArguments(), node.getMethodSelect(), node.getKind(), node.getTypeArguments());
//            return null;
//        }
    @Override
        public Void visitAssignment(AssignmentTree node,Void aVoid) {
            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
                    node.getVariable(), node.getExpression(), node.getKind(), currentPackageName);
            return null;
        }


    }

    public static void formatPtrln(String format, Object... args) {
        System.out.println(String.format(format, args));
    }


}
